package com.catdou.formatter.mvc.jackson;

import com.catdou.formatter.annotations.NullValueHandler;
import com.catdou.formatter.mvc.jackson.serializer.IntergerNullSerializer;
import com.catdou.formatter.mvc.jackson.serializer.ListNullSerializer;
import com.catdou.formatter.mvc.jackson.serializer.StringNullSerializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.PropertyBuilder;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author James
 */
public class NullValueSerializerInterceptor extends JacksonAnnotationIntrospector {

    private static Map<Class<?>, Class<? extends JsonSerializer>> serializerMap = new HashMap<>();

    static {
        serializerMap.put(String.class, StringNullSerializer.class);
        serializerMap.put(Integer.class, IntergerNullSerializer.class);
        serializerMap.put(List.class, ListNullSerializer.class);
    }

    /**
     *  返回 null 就不不处理 null
     *  @see BeanPropertyWriter#assignNullSerializer(com.fasterxml.jackson.databind.JsonSerializer)
     *  @see PropertyBuilder#buildWriter
     * @param a Annotated
     * @return
     */
    @Override
    public Object findNullSerializer(Annotated a) {
        NullValueHandler nullValueHandler = a.getAnnotation(NullValueHandler.class);
        if (nullValueHandler == null) {
            if (a instanceof AnnotatedMethod) {
                AnnotatedMethod annotatedMethod = (AnnotatedMethod) a;
                nullValueHandler = annotatedMethod.getDeclaringClass().getAnnotation(NullValueHandler.class);
            }
        }
        if (nullValueHandler != null) {
            Class<? extends JsonSerializer> using = nullValueHandler.using();
            if (using != JsonSerializer.None.class) {
                return using;
            } else {
                Class<?> filedType = a.getRawType();
                Set<Class<?>> ignoredSet = Arrays.stream(nullValueHandler.ignore()).collect(Collectors.toSet());
                if (ignoredSet.contains(filedType)) {
                    return null;
                }
                return serializerMap.get(filedType);
            }
        }
        return null;
    }

}
